package model

import (
    "errors"
    "gorm.io/gorm"
    "strings"
    "time"
    "yi-shou-backstage/util"
    "yi-shou-backstage/module/param"
)

// 文章
type Article struct {
    ID int `gorm:"primaryKey;comment:编号" json:"id,omitempty"`
    Title string `gorm:"type:varchar(256);not null;comment:标题" json:"title,omitempty" validate:"required,omitempty" label:"标题"`
    Content string `gorm:"type:text;not null;comment:内容" json:"content,omitempty" validate:"required,omitempty" label:"内容"`
    Cover string `gorm:"type:varchar(1024);comment:封面" json:"cover,omitempty" validate:"required,omitempty" label:"封面"`
    Status int `gorm:"type:int;not null;default:1;comment:状态：0-草稿，1-待审核，2-审核通过，3-审核失败，4-已删除" json:"status" validate:"required,omitempty" label:"状态"`
    PublishStart time.Time `gorm:"comment:起始时间" json:"publish_start,omitempty" validate:"omitempty" label:"起始时间"`
    PublishEnd time.Time `gorm:"comment:截止时间" json:"publish_end,omitempty" validate:"omitempty" label:"截止时间"`
    CommentCount int `gorm:"type:int;default:0;comment:评论数" json:"comment_count,omitempty"`
    ReadCount int `gorm:"type:int;default:0;comment:阅读数" json:"read_count,omitempty"`
    LikeCount int `gorm:"type:int;default:0;comment:点赞数" json:"like_count,omitempty"`
    RepostCount int `gorm:"type:int;default:0;comment:转发数" json:"repost_count,omitempty"`
    CollectCount int `gorm:"type:int;default:0;comment:收藏数" json:"collect_count,omitempty"`
    Draft bool `gorm:"type:bool;comment:是否保存为草稿" json:"draft;omitempty" validate:"omitempty"`

    // 添加关联
    ChannelID int `gorm:"type:int;not null;comment:频道id" json:"channel_id" validate:"required" label:"所属频道id"`
    Channel Channel `gorm:"foreignKey:ChannelID;constraint:OnUpdate:CASCADE"`

    Page int `gorm:"-" json:"page"`
    PerPage int `gorm:"-" json:"per_page"`
}

func CreateArticle(art Article) *Article {
    err := db.Create(&art).Error
    if err != nil {
        util.LogEntry.Errorf("Create article fialed, error = %s \n", err)
        return nil
    }
    return &art
}

func UpdateArticle (id int, obj Article) *Article {
    art := Article{ID: id}
    err := db.Model(&art).Updates(&obj).Error
    if err != nil {
        util.LogEntry.Errorf("Update article fialed, error = %s \n", err)
        return nil
    }
    return &art
}

func GetArticle(id int) *Article {
    var art Article
    err := db.First(&art, id).Error
    if errors.Is(err, gorm.ErrRecordNotFound) {
        util.LogEntry.Errorf("Article not exist, id = %d \n", id)
        return nil
    }
    return &art
}

func ListArticles(condition param.ListArticlesParam) (int64, []Article) {
    var articles []Article
    var total int64
    offset := -1
    limit := -1
    if condition.Page == 1 {
        offset = 0
        limit = condition.PerPage
    } else if condition.Page > 1 {
        offset = (condition.Page -1) * condition.PerPage
        limit = condition.PerPage
    }
    whereList := make([]string, 0)
    params := make([]interface{}, 0)
    if condition.Status != 0 {
        whereList = append(whereList, "status = ?")
        params = append(params, condition.Status)
    }
    if condition.ChannelID != 0 {
        whereList = append(whereList, "channel_id = ?")
        params = append(params, condition.ChannelID)
    }
    if condition.PublishStart != "" {
        whereList = append(whereList, "publish_start >= ?")
        params = append(params, condition.PublishStart)
    }
    if condition.PublishEnd != "" {
        whereList = append(whereList, "publish_end <= ?")
        params = append(params, condition.PublishEnd)
    }
    err := db.Where(strings.Join(whereList, " AND "), params...).Find(&articles).Count(&total).Error
    err = db.Where(strings.Join(whereList, " AND "), params...).Offset(offset).Limit(limit).Find(&articles).Error
    if err != nil {
        util.LogEntry.Errorf("List article failed, error = %s \n", err)
        return 0, nil
    }
    return total, articles
}

func DeleteArticle(id int) *Article {
    art := Article{ID: id}
    err := db.Delete(&art).Error
    if err != nil {
        util.LogEntry.Errorf("Delete article failed, error = %s \n")
        return nil
    }
    return &art
}